#include"SudokuHouse.h"
#include"SudokuCell.h"
#include"SudokuData.h"

SudokuHouse::SudokuHouse(SetType type, SudokuData* parentData) :
        SudokuCellSet(type),
        mParentData(parentData)
{
}

void SudokuHouse::sortByCandidatesAmount()
{
    /*qDebug() << "before sort:";
    for(int i=0;i<this->size();++i)
        qDebug() << *this->at(i);*/

    qSort(this->begin(), this->end(), SudokuCell::hasLessCandidates);

    /*qDebug() << "after sort:";
    for(int i=0;i<this->size();++i)
        qDebug() << *this->at(i);*/
}

SudokuCellSet SudokuHouse::getCellsWithCandidate(int candidate) const
{
    SudokuCellSet set;
    for(int i=0;i<size();++i)
        if(this->at(i)->isEmpty() && this->at(i)->getPossibl(candidate))
            set.append(this->at(i));
    return set;
}

QBitArray SudokuHouse::getCellsArrayWithCandidate(int candidate) const
{
    QBitArray bitArray(size(), false);

    for(int i=0;i<size();++i)
        if(this->at(i)->isEmpty() && this->at(i)->getPossibl(candidate))
            bitArray.setBit(i, true);

    return bitArray;
}

QVector<int> SudokuHouse::getCandidateCountVector() const
{
    //qDebug() << ">>SudokuHouse::getCandidateCountVector";
    QVector<int> countVector;

//TODO check that method, check indexes candidateInd
    for(int cellInd=0;cellInd<this->size();++cellInd)
    {
        SudokuCell* cell = this->at(cellInd);
        if(cell->isEmpty())
        {
            if(countVector.isEmpty())
                countVector.fill(0,cell->getPossiblArrSize());
            for(int candidateInd=0;candidateInd< cell->getPossiblArrSize();++candidateInd)//TODO find better way to index that vector
                countVector[candidateInd] += cell->getPossibl(candidateInd);
        }
    }

    //for(int i=0;i<countVector.size();++i)
    //    qDebug() << i << ": " << countVector.at(i) << endl;
    //qDebug() << "<<SudokuHouse::getCandidateCountVector";
    return countVector;
}

QList< QPair<int, int> > SudokuHouse::getCandidateListByCount() const
{
    qDebug() << ">>getCandidateListByCount";
    QList< QPair<int,int> > listCount;
    QVector<int> countVector = getCandidateCountVector();

    //TODO skip zero possible candidate count?
    for(int i=0;i<countVector.size();++i)
        listCount.append(QPair<int, int>(countVector.at(i),i));

    qSort(listCount.begin(), listCount.end(), SudokuHouse::sortPairs);

    for(int j=0;j<listCount.size();++j)
        qDebug() << listCount.at(j).first << ": " << listCount.at(j).second;

    qDebug() << "<<getCandidateListByCount";

    return listCount;
}

int SudokuHouse::eliminate(int num, CellFillerTypes method, int omitColInd, int omitRowInd, int omitBoxInd)
{
    int count = 0;
    for(int i=0;i<size();++i)
    {
        if(at(i)->isEmpty() &&
           at(i)->getCol() != omitColInd &&
           at(i)->getRow() != omitRowInd &&
           at(i)->getBoxIndex() != omitBoxInd &&
           at(i)->getPossibl(num) == true)
        {
            mParentData->onExcludePossibl(at(i)->getIndex(),num,method);
            ++count;
        }
    }
    return count;
}

// TODO change omitCells to list of int (index) ??
int SudokuHouse::eliminate(QList<int> numList, CellFillerTypes method, SudokuCellSet& omitCells)
{
    int count = 0;
    for(int i=0;i<size();++i)
    {
        if(at(i)->isEmpty() &&
           !omitCells.contains(at(i)))
        {
            for(int j=0;j<numList.count();++j)
            {
                if(at(i)->getPossibl(numList[j]) == true)
                {
                    mParentData->onExcludePossibl(at(i)->getIndex(),numList[j],method);
                    ++count;
                }
            }
        }
    }
    return count;
}

/*int SudokuHouse::eliminateAll(QList<int> omitNumbers, CellFillerTypes method)
{
    QList<int> eliminateList;

    for(int i=0;i<mParentData->getSize();++i)
        if(!omitNumbers.contains(i))
            eliminateList.append(i);

    SudokuCellSet empty;
    return eliminate(eliminateList,method,empty);
}*/

int SudokuHouse::eliminateAllOthers(QList<int>& cellIndexList, QList<int>& candidateList, CellFillerTypes method)
{
    int count = 0;
    foreach(int cellIndex, cellIndexList)
    {
        SudokuCell* cell = mParentData->cellAt(cellIndex);
        if(cell->isEmpty())
        {
            for(int num=0; num<mParentData->getSize(); ++num)
            {
                if(cell->getPossibl(num) && (!candidateList.contains(num)) )
                {
                    mParentData->onExcludePossibl(cellIndex, num, method);
                    ++count;
                }
            }
        }
    }
    return count;
}

bool SudokuHouse::sortPairs(const QPair<int, int> &pair1, const QPair<int, int> &pair2)//TODO not using this?
{
    return (pair1.first < pair2.first);
}

